
import { _decorator, Component, Node, Vec3 } from 'cc';
import { RoadPoint } from './RoadPoint';
const { ccclass, property } = _decorator;

var _tempVec = new Vec3();
@ccclass('Car')
export class Car extends Component {
    private _currRoadPoint?: RoadPoint | null = null;
    private _pointA = new Vec3();
    private _pointB = new Vec3();

    private _currSpeed = 0.1;
    private _isMoving: boolean = false;
    private _offset = new Vec3();

    private _originRotation = 0;
    private _targetRatation = 0;
    private _centerPoint = new Vec3();
    private _rotMeasure = 0;

    public setEntery(entry: Node) {
        this.node.setWorldPosition(entry.worldPosition);

        this._currRoadPoint = entry.getComponent(RoadPoint);
        if (!this._currRoadPoint) {
            console.warn("There's no RoadPoint in " + entry.name);
            return;
        }

        let nextPosition = this._currRoadPoint.nextStation?.worldPosition;
        if (!nextPosition) {
            nextPosition = new Vec3();
        }
        this._pointA.set(entry.worldPosition);
        this._pointB.set(nextPosition);

        const z = this._pointB.z - this._pointA.z;
        if(z !=0 ) {
            if (z < 0) {
                this.node.eulerAngles = new Vec3();
            } else {
                this.node.eulerAngles = new Vec3(0,180,0);
            }
        } else {
            const x = this._pointB.x - this._pointA.x;
            if (x > 0) {
                this.node.eulerAngles = new Vec3(0,270, 0);
            }else {
                this.node.eulerAngles = new Vec3(0,90, 0);

            }
        }
    }

    update(dt: number) {
        if (this._isMoving) {
            console.log("Moving");
            this._offset.set(this.node.worldPosition);
            switch (this._currRoadPoint?.moveType) {
                case RoadPoint.RoadMoveType.CURVE:
                    const offsetRotation = this._targetRatation - this._originRotation;
                    const currRotation = this._conversion(this.node.eulerAngles.y);
                    let nextRotation = (currRotation - this._originRotation) + 
                        (this._currSpeed * this._rotMeasure * (this._targetRatation > this._originRotation? 1: -1));

                    if (Math.abs(nextRotation) > Math.abs(offsetRotation)) {
                        nextRotation = offsetRotation;
                    }
                    const target = nextRotation + this._originRotation;
                    _tempVec.set(0, target, 0);
                    this.node.eulerAngles = _tempVec;

                    // const sin = Math.sin(nextRotation * Math.PI / 180);
                    // const cos = Math.cos(nextRotation * Math.PI / 180);
                    // const xLen = this._pointA.x - this._centerPoint.x;
                    // const zLen = this._pointA.z - this._centerPoint.z;
                    // const xPos = xLen * cos + zLen * sin + this._centerPoint.x;
                    // const zPos = -xLen * sin + zLen * cos + this._centerPoint.z;
                    // this._offset.set(xPos, 0, zPos);
                    Vec3.rotateY(this._offset, this._pointA, this._centerPoint, nextRotation * Math.PI / 180);
                    break;
            
                default:
                    const z = this._pointB.z - this._pointA.z;
                    if(z !=0 ) {
                        if (z > 0) {
                            this._offset.z += this._currSpeed;
                            this._offset.z = Math.min(this._pointB.z, this._offset.z);
                        } else {
                            this._offset.z -= this._currSpeed;
                            this._offset.z = Math.max(this._pointB.z, this._offset.z);
                        }
                    } else {
                        const x = this._pointB.x - this._pointA.x;
                        if (x > 0) {
                            this._offset.x += this._currSpeed;
                            this._offset.x = Math.min(this._pointB.x, this._offset.x);
                        }else {
                            this._offset.x -= this._currSpeed;
                            this._offset.x = Math.max(this._pointB.x, this._offset.x);
                        }
                    }
                    break;
            }
            this.node.setWorldPosition(this._offset);
            Vec3.subtract(_tempVec, this._pointB, this._offset);
            if (_tempVec.length() <= 0.01) {
                this.arriveStation();
            }
        }
    }

    public startRunning() {
        if (this._currRoadPoint) {
            this._isMoving = true;
        }
    }

    public stopRunning() {
        this._isMoving = false;
    }

    private arriveStation() {
        console.log("arrive station");
        this._pointA.set(this._pointB);
        this._currRoadPoint = this._currRoadPoint?.nextStation?.getComponent(RoadPoint);
        if (this._currRoadPoint?.nextStation) {
            this._pointB.set(this._currRoadPoint?.nextStation.worldPosition);
            if (this._currRoadPoint.moveType === RoadPoint.RoadMoveType.CURVE) {
                if (this._currRoadPoint.clockWise) {
                    this._originRotation = this._conversion(this.node.eulerAngles.y);
                    this._targetRatation = this._originRotation - 90;

                    if ((this._pointB.z < this._pointA.z && this._pointB.x > this._pointA.x) ||
                        (this._pointB.z > this._pointA.z && this._pointB.x < this._pointA.x)) {
                        this._centerPoint.set(this._pointB.x, 0, this._pointA.z);
                    } else {
                        this._centerPoint.set(this._pointA.x, 0, this._pointB.z);
                    }
                } else {
                    this._originRotation = this._conversion(this.node.eulerAngles.y);
                    this._targetRatation = this._originRotation + 90;

                    if ((this._pointB.z > this._pointA.z && this._pointB.x > this._pointA.x) ||
                        (this._pointB.z < this._pointA.z && this._pointB.x < this._pointA.x)) {
                        this._centerPoint.set(this._pointB.x, 0, this._pointA.z);
                    } else {
                        this._centerPoint.set(this._pointA.x, 0, this._pointB.z);
                    }
                }
                Vec3.subtract(_tempVec, this._pointA, this._centerPoint);

                let r = _tempVec.length();
                this._rotMeasure = 90 / (Math.PI * r / 2);
            }
        } else {
            this._isMoving = false;
            this._currRoadPoint = null;
        }
        // if (this._currRoadPoint) {
        //     let nextPosition = this._currRoadPoint.nextStation?.worldPosition;
        //     if (!nextPosition) {
        //         nextPosition = new Vec3();
        //     }
        //     this._pointB.set(nextPosition);
        // } else {
        //     this._isMoving = false;
        //     this._currRoadPoint = null;
        // }
    }

    private _conversion(value: number) {
        let a = value;
        if (a < 0) {
            a += 360;
        }

        return a;
    }
}
